package com.bonc.ioc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bonc.ioc.dao.HotwordDao;
import com.bonc.ioc.model.HotwordInfo;
import com.bonc.ioc.service.IHotwordService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author ZhangXu
 * @date 2021/4/16 11:49
 */
@Service
public class HotwordServiceImpl extends EsServiceImpl implements IHotwordService {
    private static final Logger log = LoggerFactory.getLogger(HotwordServiceImpl.class);

    @Resource
    private HotwordDao hotwordDao;

    @Override
    public void saveHotword(String text) throws IOException {
        log.info("热点词 输入={}", text);
        text = text.length() > 100 ? text.substring(0, 100) : text;
        Request request = new Request("GET", "_analyze");
        JSONObject entity = new JSONObject();
        entity.put("analyzer", "ik_smart");
        entity.put("text", text);
        request.setJsonEntity(entity.toJSONString());
        Response response = this.client.getLowLevelClient().performRequest(request);
        JSONObject tokens = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
        JSONArray arrays = tokens.getJSONArray("tokens");
        for (int i = 0; i < arrays.size(); i++) {
            JSONObject obj = JSON.parseObject(arrays.getString(i));
            String word = obj.getString("token");
            if ( word.length() > 1 ) {
                log.info("热点词 ik分词结果={}, 长度={}", word, word.length());
                int flag = hotwordDao.updateHotword(word);
                if ( flag == 0 ) {
                    hotwordDao.addHotword(word);
                }
            }
        }
    }

    @Override
    public List<String> queryHotWord() {
        return hotwordDao.selectHotword();
    }

    @Override
    public List<HotwordInfo> queryHotWordAssociation(String word) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        //过滤失效数据：logstash每分钟同步数据库,通过同步时间筛选,过滤失效数据
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.add(Calendar.MINUTE, -3);
        Calendar afterTime = Calendar.getInstance();
        afterTime.add(Calendar.MINUTE, 3);
        builder.must(QueryBuilders.rangeQuery("es_update_time").gte(sdf.format(beforeTime.getTime())).lte(sdf.format(afterTime)).format("yyyy-MM-dd HH:mm:ss"));
        if (StringUtils.isNotBlank(word)) {
            builder.must(
                    QueryBuilders.boolQuery()
                            .should( QueryBuilders.matchQuery("hotword", word) )
            );
        }
        searchSourceBuilder.query(builder);

        //创建并设置SearchRequest对象
        SearchRequest searchRequest = new SearchRequest();
        //设置request要搜索的索引和类型
        searchRequest.indices("hot_words");
        //设置SearchSourceBuilder查询属性
        searchRequest.source(searchSourceBuilder);
        log.info("ES检索命令 SearchSourceBuilder={}", searchSourceBuilder.toString());
        SearchResponse searchResponse = null;
        List<HotwordInfo> resultList = new LinkedList<>();
        try {
            searchResponse = client.search(searchRequest, COMMON_OPTIONS);
        } catch (IOException e) {
            e.printStackTrace();
        }
        assert searchResponse != null;
        SearchHit[] hits = searchResponse.getHits().getHits();
        Arrays.stream(hits).forEach(hit -> {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            HotwordInfo hotwordInfo = BeanUtil.mapToBean(sourceAsMap, HotwordInfo.class, true);
            if (!word.equals(hotwordInfo.getHotword())) {
                resultList.add(hotwordInfo);
            }
        });
        return resultList;
    }
}
